package com.kalvan.core.redis;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * @author kalvan
 * @Describe Redis缓存工具类
 */
@Component
@Slf4j
public class RedisCacheUtil {

    public static JedisPool pool;


    @Autowired(required = false)
    JedisPool jedisPool;

    /**
     * 设置缓存
     *
     * @param key   缓存key
     * @param value 缓存value
     */
    public static String set(String key, String value) {
        String ret = "";
        Jedis jedis = null;
        try {
            if (StringUtils.isBlank(key)) {
                throw new IllegalArgumentException("key must not null!");
            }
            jedis = pool.getResource();
            ret = jedis.set(key, value);
            log.debug("Redis set cache key={},value={}", key, value);
        } catch (Exception e) {
            log.error("Redis set error: {} key {} value {}", e.getMessage(), key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return ret;
    }

    /**
     * 缓存对象，并设置超时时间
     *
     * @param key
     * @param value
     * @param seconds 超时时间
     * @return
     * @see
     */
    public static String setValue(String key, Object value, int seconds) {
        String ret = "";
        Jedis jedis = null;
        try {
            if (StringUtils.isBlank(key)) {
                throw new IllegalArgumentException("key must not null!");
            }
            String jsonValue = parseJsonString(value);
            if (seconds <= 0) {
                return set(key, jsonValue);
            }
            jedis = pool.getResource();
            ret = jedis.setex(key, seconds, jsonValue);
            log.debug("Redis set cache key={},value={},seconds={}", key, jsonValue, seconds);
        } catch (Exception e) {
            log.error("Redis set error: {} key {} value {}", e.getMessage(), key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return ret;
    }

    /**
     * redis 累加
     */
    public static Long incr(String key) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            return jedis.incr(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取缓存的字符串
     *
     * @param key
     * @return
     * @see
     */
    public static String get(String key) {
        String result = null;
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            result = jedis.get(key);
        } catch (Exception e) {
            log.error("Redis get error: {} key {} ", e.getMessage(), key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }


    /**
     * 获取缓存对象
     *
     * @param key
     * @param obj
     * @return
     * @see
     */
    public static <T> Object getObjectValue(String key, Class<?> obj) {
        Object objValue = null;
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            String value = jedis.get(key);
            objValue = parseJson(value, obj);
        } catch (Exception e) {
            log.error("Redis get objValue error: " + e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return objValue;
    }

    /**
     * 设置过期时间
     *
     * @param key
     * @param seconds
     * @return
     * @see
     */
    public static Long expire(String key, int seconds) {
        Long s = null;
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            s = jedis.expire(key, seconds);
        } catch (Exception e) {
            log.error("Redis expire error: " + e.getMessage() + " - " + key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return s;
    }

    /**
     * 检查key是否存在</br>
     * setnx的含义就是SET if Not Exists，其主要有两个参数 setnx(key, value),该方法是原子的。</br>
     * 如果key不存在，则设置当前key成功，返回1；如果当前key已经存在，则设置当前key失败，返回0。</br>
     *
     * @param key
     * @param value
     * @return
     * @see
     */
    public static Long setnx(String key, String value) {
        Long s = null;
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            s = jedis.setnx(key, value);
        } catch (Exception e) {
            log.error("Redis setnx error: " + e.getMessage() + " - " + key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return s;

    }

    public static Long del(String key) {
        Long s = null;
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            s = jedis.del(key);
        } catch (Exception e) {
            log.error("Redis del error: " + e.getMessage() + " - " + key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return s;

    }

    /**
     * Object转JSON 字符串
     *
     * @param value
     * @return
     * @see
     */
    private static String parseJsonString(Object value) {
        if (value == null) {
            return "";
        }
        if ((value instanceof String)) {
            return value.toString();
        }
        if ((value instanceof List)) {
            return toJson(value);
        }
        return toJson(value);
    }

    /**
     * 模糊查询
     *
     * @param pattern
     * @return
     */
    public static List<String> redisKeys(String pattern) {
        log.info("开始模糊查询keys:{}", pattern);
        List<String> keys = new ArrayList<>();
        //获取所有连接池节点
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            keys.addAll(jedis.keys(pattern));
        } catch (Exception e) {
            log.error("获取key异常", e);
        } finally {
            log.info("关闭连接");
            //一定要关闭连接！
            jedis.close();
        }
        log.info("已获取所有keys");
        return keys;
    }

    private static String toJson(Object obj) {
        return JSON.toJSONString(obj);
    }

    private static <T> T parseJson(String json, Class<T> c) {
        return JSON.parseObject(json, c);
    }

    @PostConstruct
    public void init() {
        pool = jedisPool;
    }

}
